﻿using mozhi.smarterp.Business.Enums;
using Mozhi.Abp.Domain.BasicData;
using System;
using System.Collections.Generic;
using Volo.Abp;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;

namespace mozhi.smarterp.Business.Inventories
{
    /// <summary>
    /// 实时库存表
    /// </summary>
    public class InventoryRealTime : AuditedAggregateRoot<Guid>, IMultiTenant
    {
        public Guid? TenantId { get; private set; }

        public Guid ProductId { get; private set; }

        public Product Product { get; private set; }

        public Guid WarehouseId { get; private set; }

        public Warehouse Warehouse { get; private set; }

        public Guid? LocationId { get; private set; }

        /// <summary>
        /// 计价方式为先进先出时，为必填
        /// </summary>
        public DateTime? InboundDate { get; private set; }

        public string BatchNumber { get; private set; }

        public string SerialNumber { get; private set; }

        /// <summary>
        /// 生产日期
        /// </summary>
        public DateTime? ProductionDate { get; private set; }

        /// <summary>
        /// 保质期（天）
        /// </summary>
        public decimal? ShelfLifeDays { get; private set; }

        /// <summary>
        /// 过期日期
        /// </summary>
        public DateTime? ExpirationDate { get; private set; }

        /// <summary>
        /// 库存单位
        /// </summary>
        public Guid BasicUnitId { get; private set; }

        /// <summary>
        /// 数量
        /// </summary>
        public decimal Quantity { get; private set; }

        /// <summary>
        /// 锁定数量
        /// </summary>
        public decimal LockedQuantity { get; private set; }

        /// <summary>
        /// 可用数量
        /// </summary>
        public decimal AvailableQuantity
        {
            get
            {
                return Quantity - LockedQuantity;
            }
        }

        /// <summary>
        /// 库存状态
        /// </summary>
        public InventoryStatusType Status { get; private set; }

        private InventoryRealTime() { }

        public InventoryRealTime(Guid id, Product product,  Warehouse warehouse, Guid? locationId, DateTime? inboundDate, 
            string batchNumber, string serialNumber, DateTime? productionDate, decimal? shelfLifeDays)
        {
            Product = product;
            Warehouse = warehouse;

            Id = id;

            ProductId = Product==null ? default : Product.Id;
            WarehouseId = Warehouse==null ? default : Warehouse.Id;
            LocationId = locationId;
            InboundDate = inboundDate;
            BatchNumber = batchNumber;
            SerialNumber = serialNumber;
            ProductionDate = productionDate;
            ShelfLifeDays = shelfLifeDays;
            ExpirationDate = productionDate.HasValue && shelfLifeDays.HasValue ? productionDate.Value.AddDays((double)shelfLifeDays.Value) : null;
            BasicUnitId = Product==null ? default : Product.BasicUnitId;

            Status = InventoryStatusType.Available;

            Validate();
        }

        public void ChangeStatus(InventoryStatusType status)
        {
            Status = status;
        }

        public void IncreaseQuantity(decimal quantity)
        {
            if (quantity < 0)
                throw new UserFriendlyException("增加库存数量不能小于0", "100000");

            if (!SerialNumber.IsNullOrEmpty() && quantity != 1)
                throw new UserFriendlyException("序列号产品库存数量只能为1", "100000");

            Quantity = Quantity + quantity;
        }

        public void DecreaseQuantity(decimal quantity)
        {
            if (quantity < 0)
                throw new UserFriendlyException("减少库存数量不能小于0", "100000");

            if (quantity > AvailableQuantity)
                throw new UserFriendlyException("减少库存数量大于可用数量", "100000");

            Quantity = Quantity - quantity;
        }

        public void LockQuantity(decimal lockedQuantity)
        {
            if (Status == InventoryStatusType.Freeze)
                throw new UserFriendlyException("当前库存已冻结，无法锁定库存", "100000");

            if (AvailableQuantity < lockedQuantity)
                throw new UserFriendlyException("库存不足，无法锁定库存", "100000");

            Quantity = Quantity - lockedQuantity;

            LockedQuantity = LockedQuantity + lockedQuantity;
        }


        #region
        private void Validate()
        {
            if (Product == null)
                throw new UserFriendlyException($"产品不存在", "100000");

            Product.Validate();

            if (Warehouse == null)
                throw new UserFriendlyException($"仓库不存在", "100000");

            if (Quantity < 0)
                throw new UserFriendlyException("库存数量不能小于0", "100000");

            if (ProductionDate.HasValue && !ExpirationDate.HasValue)
                throw new UserFriendlyException("有生产日期的产品，过期日期不能为空", "100000");

            if (ProductionDate.HasValue && (ProductionDate.Value > ExpirationDate.Value))
                throw new UserFriendlyException("生产日期不能大于过期日期", "100000");

            Warehouse.Validate();
            Warehouse.ValidateLoaction(LocationId);

            Check.NotDefaultOrNull<Guid>(BasicUnitId, nameof(BasicUnitId));
            Check.NotDefaultOrNull<decimal>(Quantity, nameof(Quantity));
        }
        #endregion
    }
}
